package com.example.netty.chatSystem.server;

import com.example.netty.chatSystem.currency.LengthField;
import com.example.netty.chatSystem.handler.ChatReceiveHandler;
import com.example.netty.chatSystem.handler.MyChannelInboundHandlerAdapter;
import com.example.netty.chatSystem.handler.QuitHandler;
import com.example.netty.chatSystem.message.MessageCodec1;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Server {
    public static void main(String[] args) {
        NioEventLoopGroup boos = new NioEventLoopGroup();
        NioEventLoopGroup work = new NioEventLoopGroup();
        MyChannelInboundHandlerAdapter myChannelInboundHandlerAdapter = new MyChannelInboundHandlerAdapter();
        ChatReceiveHandler chatReceiveHandler = new ChatReceiveHandler();
        QuitHandler quitHandler = new QuitHandler();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boos,work);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                    nioSocketChannel.pipeline().addLast(new LengthField());
                    nioSocketChannel.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));
                    nioSocketChannel.pipeline().addLast(new MessageCodec1());

                    //用来判断是不是 读空闲时间过长 或 写时间过长
                    //5s 内没有收到 channel 的数据 IdleState#READER_IDLE 事件
                    nioSocketChannel.pipeline().addLast(new IdleStateHandler(
                            5,0,0));
                    //ChannelDuplexHandler 可以同时处理 入站和出站
                    nioSocketChannel.pipeline().addLast(new ChannelDuplexHandler(){
                        //用来触发特殊事件
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            IdleStateEvent event = (IdleStateEvent) evt;
                            //触发了读空闲事件
                            if (event.state() == IdleState.READER_IDLE) {
                                log.debug("5s 未读到数据");
                                ctx.channel().close();
                            }
                        }
                    });


                    nioSocketChannel.pipeline().addLast(myChannelInboundHandlerAdapter);
                    nioSocketChannel.pipeline().addLast(chatReceiveHandler);
                    nioSocketChannel.pipeline().addLast(quitHandler);
                }
            });
            ChannelFuture sync = serverBootstrap.bind(8080).sync();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
